
/******************************************************************************/
/*                        --安信可科技有限公司--                        */
/*
//  函数说明：main.c                                                              
//  说明：该程序用于测试lora模块                                                                
//  编写人员： sky                                                                 
// 编写日期： 2016-11-24                                                         
// 版本号:V1.0
// 维护日志：
//
//                                                          
*/ 
// 免责声明：该程序仅供参考学习，若自定义其他功能，请查看参考手册
// (c) Anxinke Corporation. All rights reserved.                                                               
/******************************************************************************/

#include "sx1278.h"
// #include "reg51.hcd"
#include <stdio.h>
#include <bcm2835.h>


#define RESET_PIN           22

#define SPI_NSS_PIN         16


lpCtrlTypefunc_t lpTypefunc = { 0, 0 };

unsigned char power_data[8] = { 0x80, 0x80, 0x80, 0x83, 0x86, 0x89, 0x8c, 0x8f };

// lpCtrlTypefunc_t ctrlTypefunc = 
// { 
//     RF_SPI_MasterIO, 
//     RF_SPI_READ_BYTE, 
//     cmdSwitchEn,
// };

// unsigned char Frequency[3] = { 0x6c, 0x80, 0x00 };    // 470Mhz
unsigned char Frequency[3] = { 0x6c, 0x80, 0x00 };      // 430Mhz 频率设置
unsigned char powerValue = 7;
unsigned char SpreadingFactor = 12;    //扩频因子7-12
unsigned char CodingRate = 2;        //1-4
unsigned char Bw_Frequency = 7;      //带宽6-9
unsigned char RF_EX0_STATUS;
unsigned char CRC_Value;
unsigned char SX1278_RLEN;
//unsigned char recv[512];


void Delay1s(unsigned int ii)
{
    int j;

    while(ii--)
    {
        for(j=0; j<1000; j++);
    }
}

/*
    function:SX1278 restart
*/
void SX1276Reset(void) 
{
    bcm2835_gpio_write(RESET_PIN, LOW);
    printf("reset pin low\n");
    bcm2835_delay(500);
    bcm2835_gpio_write(RESET_PIN, HIGH);
    printf("reset pin high\n");
    bcm2835_delay(500);

    // spi_nss_enable();
    // printf("spi nss enable\n");
    // bcm2835_delay(500);
    // spi_nss_disable();
    // printf("spi nss disable\n");
    // bcm2835_delay(500);
}

/*
    function:control GPIO-EN
*/
void spi_nss_enable(void)
{
    bcm2835_gpio_write(SPI_NSS_PIN, LOW);
}

void spi_nss_disable(void)
{
    bcm2835_gpio_write(SPI_NSS_PIN, HIGH);
}

// void RF_SPI_MasterIO(unsigned char out) 
// {
//     unsigned char i;

//     for (i = 0; i < 8; i++) 
//     {
//         if (out & 0x80)     /* check if MSB is high */
//             RF_SDI_H;
//         else                /* if not, set to low */
//             RF_SDI_L;

//         RF_CKL_H;           /* toggle clock high */
//         out = (out << 1);   // shift 1 place for next bit 
//         RF_CKL_L;           /* toggle clock low */
//     }
// }

// unsigned char RF_SPI_READ_BYTE(void) 
// {
//     unsigned char j;
//     unsigned char i;

//     j = 0;
//     for (i = 0; i < 8; i++) 
//     {
//         RF_CKL_H;
//         j = (j << 1);           // shift 1 place to the left or shift in 0 //
//         if ( SX1278_SDO)        // check to see if bit is high //
//             j = j | 0x01;       // if high, make bit high //
//                                 // toggle clock high //
//         RF_CKL_L;               // toggle clock low //
//     }

//     return j;                   // toggle clock low //
// }

void register_rf_func(lpCtrlTypefunc_t *func) 
{
    if (func->lpByteWritefunc != 0) 
    {
        lpTypefunc.lpByteWritefunc = func->lpByteWritefunc;
    }

    if (func->lpByteReadfunc != 0) 
    {
        lpTypefunc.lpByteReadfunc = func->lpByteReadfunc;
    }

//     if (func->lpSwitchEnStatus != 0) 
//     {
//         lpTypefunc.lpSwitchEnStatus = func->lpSwitchEnStatus;
//     }
}

unsigned char SX1276ReadBuffer(unsigned char addr) 
{
    unsigned char value;

    // lpTypefunc.lpSwitchEnStatus(enOpen);    // NSS = 0;
    spi_nss_enable();
    lpTypefunc.lpByteWritefunc(addr & 0x7f);
    value = lpTypefunc.lpByteReadfunc();
    // lpTypefunc.lpSwitchEnStatus(enClose);   // NSS = 1;
    spi_nss_disable();

    // printf("%s: write addr %02x, read value %02x\n", __func__, addr, value);

    return value;
}

void SX1276WriteBuffer(unsigned char addr, unsigned char buffer) 
{
    // lpTypefunc.lpSwitchEnStatus(enOpen);    // NSS = 0;
    spi_nss_enable();
    lpTypefunc.lpByteWritefunc(addr | 0x80);
    lpTypefunc.lpByteWritefunc(buffer);
    // lpTypefunc.lpSwitchEnStatus(enClose);   // NSS = 1;
    spi_nss_disable();

    // printf("%s: write addr %02x, write value %02x\n", __func__, addr, buffer);
}

/*
    function:set sx1278 work mode ,here you can control the mode which is send or recieve 
    parm: 
*/
void  SX1276LoRaSetOpMode(RFMode_SET opMode) 
{
    unsigned char opModePrev;

    opModePrev = SX1276ReadBuffer(REG_LR_OPMODE);
    // printf("get Device modes %x\n", opModePrev);
    opModePrev &= 0xf8;
    opModePrev |= (unsigned char) opMode;
    SX1276WriteBuffer(REG_LR_OPMODE, opModePrev);
}

void  SX1276LoRaSetRFFrequency(void) 
{
    SX1276WriteBuffer( REG_LR_FRFMSB, Frequency[0]);    // 0x04射频载波频率最高有效位
    SX1276WriteBuffer( REG_LR_FRFMID, Frequency[1]);    // 0x07射频载波频率中间有效位
    SX1276WriteBuffer( REG_LR_FRFLSB, Frequency[2]);    // 0x00射频载波频率最低有效位
}

void  SX1276LoRaSetNbTrigPeaks(unsigned char value) 
{
    unsigned char RECVER_DAT;

    RECVER_DAT = SX1276ReadBuffer(0x31);
    RECVER_DAT = (RECVER_DAT & 0xF8) | value;
    SX1276WriteBuffer(0x31, RECVER_DAT);
}

void  SX1276LoRaSetSpreadingFactor(unsigned char factor) 
{
    unsigned char RECVER_DAT;

    SX1276LoRaSetNbTrigPeaks(3);
    RECVER_DAT = SX1276ReadBuffer( REG_LR_MODEMCONFIG2);
    RECVER_DAT = (RECVER_DAT & RFLR_MODEMCONFIG2_SF_MASK) | (factor << 4);
    SX1276WriteBuffer( REG_LR_MODEMCONFIG2, RECVER_DAT);
}

void  SX1276LoRaSetErrorCoding(unsigned char value) 
{
    unsigned char RECVER_DAT;

    RECVER_DAT = SX1276ReadBuffer( REG_LR_MODEMCONFIG1);
    RECVER_DAT = (RECVER_DAT & RFLR_MODEMCONFIG1_CODINGRATE_MASK) | (value << 1);
    SX1276WriteBuffer( REG_LR_MODEMCONFIG1, RECVER_DAT);
    // LoRaSettings.ErrorCoding = value;
}

void  SX1276LoRaSetSignalBandwidth(unsigned char bw) 
{
    unsigned char RECVER_DAT;

    RECVER_DAT = SX1276ReadBuffer( REG_LR_MODEMCONFIG1);
    RECVER_DAT = (RECVER_DAT & RFLR_MODEMCONFIG1_BW_MASK) | (bw << 4);
    SX1276WriteBuffer( REG_LR_MODEMCONFIG1, RECVER_DAT);
    // LoRaSettings.SignalBw = bw;
}

void  SX1276LoRaSetImplicitHeaderOn(BOOL enable) 
{
    unsigned char RECVER_DAT;

    RECVER_DAT = SX1276ReadBuffer( REG_LR_MODEMCONFIG1);
    RECVER_DAT = (RECVER_DAT & RFLR_MODEMCONFIG1_IMPLICITHEADER_MASK) | (enable);
    SX1276WriteBuffer( REG_LR_MODEMCONFIG1, RECVER_DAT);
}

void  SX1276LoRaSetPayloadLength(unsigned char value) 
{
    SX1276WriteBuffer( REG_LR_PAYLOADLENGTH, value);
}

void  SX1276LoRaSetSymbTimeout(unsigned int value) 
{
    unsigned char RECVER_DAT[2];

    RECVER_DAT[0] = SX1276ReadBuffer( REG_LR_MODEMCONFIG2);
    RECVER_DAT[1] = SX1276ReadBuffer( REG_LR_SYMBTIMEOUTLSB);
    RECVER_DAT[0] = (RECVER_DAT[0] & RFLR_MODEMCONFIG2_SYMBTIMEOUTMSB_MASK) | ((value >> 8) & ~RFLR_MODEMCONFIG2_SYMBTIMEOUTMSB_MASK);
    RECVER_DAT[1] = value & 0xFF;
    SX1276WriteBuffer( REG_LR_MODEMCONFIG2, RECVER_DAT[0]);
    SX1276WriteBuffer( REG_LR_SYMBTIMEOUTLSB, RECVER_DAT[1]);
}

void  SX1276LoRaSetMobileNode(BOOL enable) 
{
    unsigned char RECVER_DAT;

    RECVER_DAT = SX1276ReadBuffer( REG_LR_MODEMCONFIG3);
    RECVER_DAT = (RECVER_DAT & RFLR_MODEMCONFIG3_MOBILE_NODE_MASK) | (enable << 3);
    SX1276WriteBuffer( REG_LR_MODEMCONFIG3, RECVER_DAT);
}

void  RF_RECEIVE(void) 
{
    SX1276LoRaSetOpMode(Stdby_mode);
    SX1276WriteBuffer(REG_LR_IRQFLAGSMASK, IRQN_RXD_Value);  //打开发送中断
    SX1276WriteBuffer(REG_LR_HOPPERIOD, PACKET_MIAX_Value);
    SX1276WriteBuffer( REG_LR_DIOMAPPING1, 0x00);           // DIO0 RxDone
    SX1276WriteBuffer( REG_LR_DIOMAPPING2, 0x00);
    SX1276LoRaSetOpMode(Receiver_mode);
    // lpTypefunc.paSwitchCmdfunc(rxOpen);
}

void  SX1276LoRaSetPacketCrcOn(BOOL enable) 
{
    unsigned char RECVER_DAT;

    RECVER_DAT = SX1276ReadBuffer( REG_LR_MODEMCONFIG2);
    RECVER_DAT = (RECVER_DAT & RFLR_MODEMCONFIG2_RXPAYLOADCRC_MASK) | (enable << 2);
    SX1276WriteBuffer( REG_LR_MODEMCONFIG2, RECVER_DAT);
}

void  SX1276LoRaFsk(Debugging_fsk_ook opMode) 
{
    unsigned char opModePrev;

    opModePrev = SX1276ReadBuffer(REG_LR_OPMODE);
    opModePrev &= 0x7F;
    opModePrev |= (unsigned char) opMode;
    SX1276WriteBuffer( REG_LR_OPMODE, opModePrev);
}


void  SX1276LoRaSetRFPower(unsigned char power) 
{
    SX1276WriteBuffer( REG_LR_PADAC, 0x87);
    SX1276WriteBuffer( REG_LR_PACONFIG, power_data[power]);
}

/*
    function :you must call it ,the function is to init the module.
*/
unsigned char sx1278_gpio_init(void)
{
    if (!bcm2835_init())
    {
        printf("bcm2835_init failed. Are you running as root??\n");
        return -1;
    }

    bcm2835_gpio_fsel(SPI_NSS_PIN, BCM2835_GPIO_FSEL_OUTP );
    bcm2835_gpio_fsel(RESET_PIN, BCM2835_GPIO_FSEL_OUTP );
    return 0;
}

void  SX1276LORA_INT(void)
{    
    SX1276LoRaSetOpMode(Sleep_mode);        // 设置睡眠模式0x01
    SX1276LoRaFsk(LORA_mode);               // 设置扩频模式,只能在睡眠模式下修改
    SX1276LoRaSetOpMode(Stdby_mode);        // 设置为普通模式
    SX1276WriteBuffer( REG_LR_DIOMAPPING1, GPIO_VARE_1);    // DIO0 RxDone
    SX1276WriteBuffer( REG_LR_DIOMAPPING1, GPIO_VARE_1);
    SX1276WriteBuffer( REG_LR_DIOMAPPING2, GPIO_VARE_2);
    SX1276LoRaSetRFFrequency();
    SX1276LoRaSetRFPower(powerValue);
    SX1276LoRaSetSpreadingFactor(SpreadingFactor);  // 扩频因子设置
    SX1276LoRaSetErrorCoding(CodingRate);           // 有效数据比
    SX1276LoRaSetPacketCrcOn(true);                 // CRC 校验打开
    SX1276LoRaSetSignalBandwidth(Bw_Frequency);     // 设置扩频带宽
    SX1276LoRaSetImplicitHeaderOn(false);           // 同步头是显性模式
    SX1276LoRaSetPayloadLength(0xff);               // 0x22 timeout中断
    SX1276LoRaSetSymbTimeout(0x3FF);
    SX1276LoRaSetMobileNode(true);                  // 低数据的优化
    RF_RECEIVE();
    printf("init finish\n");
}

/*
function :if you want to send data,you can call it 
RF_TRAN_P:data
ASM_i:the length of the data
*/
void  FUN_RF_SENDPACKET(unsigned char *RF_TRAN_P, unsigned char LEN) 
{
    unsigned char ASM_i;
    // int i;

    // printf("msg:");
    // for (i=0; i<LEN; i++)
    // {
    //     printf(" %d", *(RF_TRAN_P + i));
    // }
    // printf("\n");
    
    // lpTypefunc.paSwitchCmdfunc(txOpen);
    SX1276LoRaSetOpMode(Stdby_mode);
    SX1276WriteBuffer( REG_LR_HOPPERIOD, 0);                //不做频率跳变
    SX1276WriteBuffer(REG_LR_IRQFLAGSMASK, IRQN_TXD_Value); //打开发送中断
    SX1276WriteBuffer( REG_LR_PAYLOADLENGTH, LEN);          //最大数据包
    SX1276WriteBuffer( REG_LR_FIFOTXBASEADDR, 0);
    SX1276WriteBuffer( REG_LR_FIFOADDRPTR, 0);
    // lpTypefunc.lpSwitchEnStatus(enOpen);
    spi_nss_enable();
    lpTypefunc.lpByteWritefunc(0x80);

    for (ASM_i = 0; ASM_i < LEN; ASM_i++) 
    {
        lpTypefunc.lpByteWritefunc(*RF_TRAN_P);
        RF_TRAN_P++;
    }

    // lpTypefunc.lpSwitchEnStatus(enClose);
    spi_nss_disable();
    SX1276WriteBuffer(REG_LR_DIOMAPPING1, 0x40);    // DIO0 TxDone
    SX1276WriteBuffer(REG_LR_DIOMAPPING2, 0x00);
    SX1276LoRaSetOpMode(Transmitter_mode);
}

